package com.minisoft.aop;

import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class PropertyChangeAspect {

    private static final ThreadLocal<Map<String, Object>> changes = new ThreadLocal<>();

    public static <T> T createProxy(T target) {
        return (T) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                (proxy, method, args) -> {
                    if (method.getName().startsWith("set")) {
                        String propertyName = method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4);
                        Object oldValue = getFieldValue(target, propertyName);
                        Object newValue = args[0];
                        Object result = method.invoke(target, args);
                        if (!Objects.equals(oldValue, newValue)) {
                            changes.get().put(propertyName, newValue);
                        }
                        return result;
                    } else {
                        return method.invoke(target, args);
                    }
                });
    }

    public static Map<String, Object> getChanges() {
        return changes.get();
    }

    public static void clearChanges() {
        changes.remove();
    }

    private static Object getFieldValue(Object target, String fieldName) {
        try {
            Field field = target.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(target);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}